using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Mtool.FSM
{
    public delegate void LogChangeHandler(string logContent);

    public class Logger
    {
        private string filepath = "default.log";

        private System.IO.StreamWriter logWriter;

        private bool consoleShow = true;

        private Logger(string fileName)
        {
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.WriteLine("Create Log...");
            filepath = System.IO.Directory.GetCurrentDirectory() + "\\" + fileName;
            if (System.IO.File.Exists(filepath))
            {
                System.IO.File.Delete(filepath);
            }
            Console.WriteLine("Log Created!");
        }

        private static string timedString(string name)
        {
            DateTime now = DateTime.Now;
            return string.Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}", now.Year, now.Month, now.Day,
                now.Hour, now.Minute, now.Second, name);
        }

        private static Logger instance = new Logger("mtool.log");

        //private static Logger feedLogger = new Logger(timedString("feed.log"));

        public event LogChangeHandler OnLogGrown;

        public bool ConsoleEnabled
        {
            get { return consoleShow; }
            set { consoleShow = value; }
        }

        public static Logger Instance
        {
            get { return instance;  }
        }

        private string TimedThreadedString(string str)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(DateTime.Now.ToLongTimeString());
            sb.Append(" : ");
            sb.Append(string.Format("[thread:{0}]", System.Threading.Thread.CurrentThread.ManagedThreadId));
            sb.Append(str);

            return sb.ToString();
        }

        public void WriteLog(string line, params object[] args)
        {
            WriteLog(ConsoleColor.Gray, line, args);
        }


        public void WriteLog(ConsoleColor color, string line, params object[] args)
        {
            lock (filepath)
            {                
                using (logWriter = new System.IO.StreamWriter(filepath, true))
                {
                    Console.ForegroundColor = color;//default                           
                    string strToWrite = TimedThreadedString(string.Format(line, args));
                    if(consoleShow)
                        Console.WriteLine(strToWrite);
                    logWriter.WriteLine(strToWrite);
                    logWriter.Flush();
                    if (OnLogGrown != null)
                        OnLogGrown(strToWrite);
                }
            }
        }

        public void Info(string line, params object[] args)
        {
            WriteLog(ConsoleColor.White, "[Info]" + line, args);
        }

        public void Verbose(string line, params object[] args)
        {
            WriteLog(ConsoleColor.Gray, " [Verbose] "+line, args);
        }

        public void Warn(string line, params object[] args)
        {            
            WriteLog(ConsoleColor.Cyan, " [Warn] " + line, args);
        }

        public void Fatal(string line, params object[] args)
        {
            WriteLog(ConsoleColor.DarkRed, " [Fatal] " + line, args);
        }

        public void Error(string line, params object[] args)
        {
            WriteLog(ConsoleColor.Red, " [Error] " + line, args);
        }

        public void Error(Exception ex)
        {
            WriteLog(ConsoleColor.Red, " [Error] {0} at\n\r{1}", ex.Message, ex.StackTrace);
        }

        public void Warn(Exception ex)
        {
            WriteLog(ConsoleColor.Cyan, " [Warn] {0} at\n\r{1}", ex.Message, ex.StackTrace);
        }

        public void Result(string line, params object[] args)
        {
            WriteLog(ConsoleColor.Yellow, " [Result] " + line, args);
        }

    }
}
